package cn.harry.cabinet.hardware

import android.content.Context
import android.util.Log
import cn.harry.cabinet.hardware.device.CardReaderDevice
import cn.harry.cabinet.model.enums.DeviceType
import cn.harry.cabinet.repository.HardwareDeviceRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

/**
 * 硬件设备管理器
 * 负责管理所有硬件设备（锁控板、刷卡器等）的连接和状态监控
 * 
 * 职责：
 * - 设备连接管理
 * - 连接状态监控
 * - 错误处理和自动恢复
 * - 数据接收由具体设备类（CardReaderDevice）负责
 */
class HardwareDeviceManager private constructor(
    context: Context
) {

    companion object {
        private const val TAG = "HardwareDeviceManager"

        @Volatile
        private var INSTANCE: HardwareDeviceManager? = null

        fun getInstance(context: Context): HardwareDeviceManager {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: HardwareDeviceManager(context.applicationContext).also { INSTANCE = it }
            }
        }
    }

    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private val serialPortManager = SerialPortManager.getInstance()

    // 硬件设备列表（按设备类型管理）
    private val devices = mutableMapOf<DeviceType, CardReaderDevice>()

    // 连接状态
    private val _isConnected = MutableStateFlow(false)
    val isConnected: StateFlow<Boolean> = _isConnected.asStateFlow()

    // 自动恢复状态标志
    private var isAutoRecovering = false

    // Repository 实例
    private val hardwareDeviceRepository = HardwareDeviceRepository(context.applicationContext as android.app.Application)

    // 设备管理监听器（只监听连接状态和错误，不处理数据）
    private val deviceManagementListener = object : SerialCommunicationListenerAdapter() {
        override fun onConnectionSuccess(devicePath: String, config: SerialPortManager.SerialConfig) {
            Log.i(TAG, "串口连接成功: $devicePath")
        }

        override fun onConnectionFailed(devicePath: String, error: String, exception: Exception?) {
            Log.e(TAG, "串口连接失败: $devicePath, 错误: $error")
        }

        override fun onConnectionClosed(devicePath: String, reason: String) {
            Log.i(TAG, "串口连接关闭: $devicePath, 原因: $reason")
            _isConnected.value = false
        }

        override fun onCommunicationError(
            devicePath: String,
            errorType: SerialCommunicationListener.ErrorType,
            errorMessage: String,
            exception: Exception?
        ) {
            Log.e(TAG, "通信错误: $devicePath, 类型: $errorType, 消息: $errorMessage")

            // 检查是否是文件描述符错误且不在恢复过程中
            if (errorType == SerialCommunicationListener.ErrorType.IO_ERROR &&
                (errorMessage.contains("EBADF") || errorMessage.contains("Bad file number")) &&
                !isAutoRecovering
            ) {

                Log.w(TAG, "检测到文件描述符错误，尝试自动恢复连接")

                // 设置恢复标志，防止重复恢复
                isAutoRecovering = true

                // 异步尝试自动恢复
                scope.launch {
                    try {

                        Log.i(TAG, "等待2秒后开始自动恢复...")
                        delay(2000) // 等待2秒再尝试恢复

                        val recovered = serialPortManager.tryAutoRecover()
                        if (recovered) {
                            Log.i(TAG, "自动恢复连接成功，等待连接稳定...")

                            // 等待连接稳定
                            delay(1000)

                            // 重新初始化所有设备（但不立即刷新状态）
                            Log.i(TAG, "开始重新初始化设备...")
                            initializeDevicesAfterRecovery()
                        } else {
                            Log.e(TAG, "自动恢复连接失败")

                        }
                    } catch (e: Exception) {
                        Log.e(TAG, "自动恢复过程中发生异常: ${e.message}", e)

                    } finally {
                        // 清除恢复标志
                        isAutoRecovering = false
                    }
                }
            } else if (isAutoRecovering) {
                Log.d(TAG, "正在自动恢复中，忽略此次通信错误")
            }
        }

        override fun onDeviceStatusChanged(
            deviceAddress: Byte,
            deviceName: String,
            oldStatus: String,
            newStatus: String
        ) {
            Log.i(
                TAG,
                "设备状态变化: $deviceName (0x${deviceAddress.toString(16)}) $oldStatus -> $newStatus"
            )
        }
    }

    init {
        // 注册设备管理监听器（只监听连接状态和错误，不处理数据）
        serialPortManager.addCommunicationListener(deviceManagementListener)
        Log.d(TAG, "HardwareDeviceManager 初始化完成，数据处理由 CardReaderDevice 负责")
    }

    /**
     * 从数据库加载设备配置
     */
    private suspend fun loadDevicesFromDatabase() {
        try {
            devices.clear()

            // 从 Repository 读取启用的设备配置
            val enabledDevices = hardwareDeviceRepository.getEnabledDevicesList()
            Log.i(TAG, "从数据库加载到 ${enabledDevices.size} 个启用的设备")

            // 创建设备实例
            enabledDevices.forEach { dbDevice ->
                when (dbDevice.deviceType) {
                    DeviceType.CARD_READER -> {
                        val cardReaderDevice = CardReaderDevice(
                            deviceName = dbDevice.deviceName,
                            serialPortPath = dbDevice.serialPort
                        )
                        devices[DeviceType.CARD_READER] = cardReaderDevice
                        Log.i(TAG, "创建刷卡器设备: ${dbDevice.deviceName}, 串口: ${dbDevice.serialPort}")
                    }
                    DeviceType.LOCK_CONTROLLER -> {
                        // 锁控板设备（预留）
                        Log.d(TAG, "锁控板设备暂不支持: ${dbDevice.deviceName}")
                    }
                }
            }

            if (devices.isEmpty()) {
                Log.w(TAG, "数据库中没有启用的设备配置！！！")
            }

        } catch (e: Exception) {
            Log.e(TAG, "从数据库加载设备配置失败: ${e.message}", e)
        }
    }


    /**
     * 连接串口并初始化所有设备
     */
    suspend fun connectAndInitialize(): Boolean {
        return try {
            Log.i(TAG, "开始连接硬件设备...")

            // 从数据库加载设备配置
            loadDevicesFromDatabase()

            // 获取刷卡器设备
            val cardReader = devices[DeviceType.CARD_READER]
            if (cardReader == null) {
                Log.e(TAG, "未找到刷卡器设备配置")
                return false
            }

            // 从 Repository 获取刷卡器配置
            val dbDevice = hardwareDeviceRepository.getDeviceByType(DeviceType.CARD_READER)
            if (dbDevice == null) {
                Log.w(TAG, "数据库中未找到刷卡器配置，使用默认配置")
            }

            // 连接刷卡器串口（使用数据库配置或默认配置）
            val cardReaderConfig = SerialPortManager.SerialConfig(
                devicePath = dbDevice?.serialPort ?: "/dev/ttyS4",
                baudRate = dbDevice?.baudRate ?: 9600,
                dataBits = dbDevice?.dataBits ?: 8,
                stopBits = dbDevice?.stopBits ?: 1,
                parity = dbDevice?.parity ?: 0
            )

            Log.i(TAG, "刷卡器配置: 串口=${cardReaderConfig.devicePath}, 波特率=${cardReaderConfig.baudRate}")

            // 连接串口
            val cardReaderConnected = serialPortManager.connect(cardReaderConfig)
            if (!cardReaderConnected) {
                Log.w(TAG, "刷卡器串口连接失败")
                _isConnected.value = false
                return false
            }

            // 启动刷卡器自动监听
            try {
                cardReader.startAutoListening()
                Log.i(TAG, "刷卡器自动监听模式已启动")
            } catch (e: Exception) {
                Log.w(TAG, "启动刷卡器监听失败: ${e.message}")
            }

            _isConnected.value = true

            Log.i(TAG, "硬件设备连接完成")
            true

        } catch (e: Exception) {
            Log.e(TAG, "硬件设备连接异常: ${e.message}", e)
            _isConnected.value = false
            false
        }
    }

    /**
     * 断开所有设备连接
     */
    fun disconnectAll() {
        Log.i(TAG, "断开所有硬件设备连接")

        // 停止刷卡器自动监听
        devices[DeviceType.CARD_READER]?.stopAutoListening()

        // 断开串口连接
        serialPortManager.disconnect()

        _isConnected.value = false
    }

    /**
     * 获取刷卡器设备
     */
    fun getCardReaderDevice(): CardReaderDevice? {
        return devices[DeviceType.CARD_READER]
    }

    /**
     * 恢复连接后重新初始化设备
     */
    private suspend fun initializeDevicesAfterRecovery() {
        try {
            Log.i(TAG, "开始恢复后的设备初始化...")

            // 重新启动刷卡器监听
            devices[DeviceType.CARD_READER]?.startAutoListening()
            Log.i(TAG, "刷卡器恢复完成")

        } catch (e: Exception) {
            Log.e(TAG, "设备恢复初始化异常: ${e.message}", e)
        }
    }


    /**
     * 释放资源
     */
    fun release() {
        serialPortManager.removeCommunicationListener(deviceManagementListener)
        scope.cancel()
        Log.d(TAG, "HardwareDeviceManager 资源已释放")
    }
}